Skip to content

Preview 1.84.1 - Part 2#868

Open
neon-nyan wants to merge 39 commits intopreviewfrom
main
Open

Preview 1.84.1 - Part 2#868
neon-nyan wants to merge 39 commits intopreviewfrom
main

Conversation

@neon-nyan
Copy link
Copy Markdown
Member

@neon-nyan neon-nyan commented Apr 5, 2026

Superseeding from #862

UpdateIsAvailable-Campaign-Columbina

Preview 1.84.1 (Codename: Columbina)

Hewwo, it's neon-nyan here~

It's beeeeeen a while since the last 1.83.x update. For now, this release is focusing on more quality improvements, bug fixes and internal code reworks rather than new features as we are preparing on reworking Collapse for new codebase.

That being said, this 1.84 update will be the marked as the last V1 release after roughly 4 years since the start of this project as we are going to move into V2 codebase starting this year (at Q3 or Q4 2026). Thank you so much for your continous support and interest in this project💖

Without further ado, let's dig into what's new in this release so far.

What's new?

Reworked Background System

Since months, HoYoverse has updated HoYoPlay to support multiple background to display, including static image and dynamic background ones. This has been our backlog since this release as due to "spaghetti-code" nature of our entire codebase, this made us harder to adapt the changes and thus making Collapse still only support one static background image.

Thanks to this massive rework, we are now able to pull-off this feature by splitting the parts of the code into its own element, making it more easier and more manageable for the change and for incoming improvements.

We are also moving to FFmpeg as our secondary library for background video decoder if no built-in codec is present. You will be prompted to install the FFmpeg library if none of the required built-in Windows Media Foundation codec for VP9 or any codec is present.

FFmpeg is licensed and distributed under GNU Lesser General Public License, version 2.1 (LGPLv2.1)

2026-03-22.20-02-46.webm

The experience might still be sluggish due to rushed implementation. But this will be improved in future updates🤞

Update: 2026/03/27

Due to corrupted video background situation in any regions for Zenless Zone Zero game, FFmpeg has been set as a default decoder for Collapse Launcher now (You can opt-in for using built-in Windows Media Foundation decoder, though). You might be asked to install a new one if you don't have any defined in your system's Environment Variable.

2026-03-27.11-55-13.webm

Reworked Localization System #861

This is more like development-experience improvement rather than user focused ones. Previously in order to implement the localization for new elements, we have to manually map each class properties to represented JSON entries. Thanks to newly source-generated class mapper, every JSON entries will be mapped automatically. Each class properties can now be bind into UI element directly, making the UI able to update the visual itself rather than being told manually, one-by-one (which is expensive).

Reworked Download Speed Limiter #859

The feature has been long broken since last 1.83.x release due to inconsistency and changes to other download-related libraries. Even though if you're enabling this feature, you might experience that the download speed "isn't actually being limited" and noticing that your bandwidth is still being fully utilized. This feature should now be fully fixed by decentralizing the code of the feature into its own library and making it easier to maintain.

This feature could also be applied for any game plugins whose have v1-update4 API standard fully implemented.

Minor UI Adjustments

Not so noticeable UI changes at all. But it's worth to mention here.

1. News Carousel Design

image

2. About Card

image

Other New Changes

  • [New] Adding Files Clean-up Button to the Menu Bar, by @bagusnl
image
  • [Imp] Switching Static Libraries Compiler from MSVC 19 to Clang 20.1, by @neon-nyan
  • [Imp] Caching Page Loading, by @neon-nyan
  • [Imp] Detach SDK Loading (for Sentry, Libsql.Client), by @neon-nyan
  • [Imp] Add Plugin Details (Breadcrumbs) to Sentry Reports, by @bagusnl
  • [Imp] Update overlay mask according to UI changes, by @shatyuka
  • [New] Implement async preload download with per-file progress callbacks Implement async preload download with per-file progress callbacks #865, by @Cryotechnic
  • [Fix] Remove ZZZ Game Settings Resolution Limit, by @shatyuka
  • [Fix] Invalid Encoding while saving ZZZ Game Settings Profile (GENERAL_DATA.bin), by @shatyuka
  • [Fix] Deleted assets still getting downloaded while updating Honkai: Star Rail and Zenless Zone Zero, by @neon-nyan
    This caused by the filtering of the asset is still being redirected to FilterSophonPatchAssetList, which is unused rather than to FilterAssetList. This causes the supposedly deleted assets to get included, causing files to be redownloaded if not exist.
  • [Fix] Fix Honkai Impact 3rd cutscene detection on Game Repair, by @neon-nyan
  • [Imp] Localization updates, by localizers 🥳
    • de-DE - German (Progress: 100%)
    • es-419 - Spanish (Latin America)(Progress: 100%)
    • fr-FR - French (Progress: 98%)
    • id-ID - Bahasa Indonesia (Progress: 100%)
    • it-IT - Italian (Progress: 45%)
    • ja-JP - Japanese (Progress: 100%)
    • ko-KR - Korean (Progress: 87%)
    • nl-NL - Dutch (Progress: 100%)
    • pl-PL - Polish (Progress: 55%)
    • pt-BR - Portuguese (Brazil)(Progress: 72%)
    • pt-PT - Portuguese (Portugal)(Progress: 65%)
    • ru-RU - Russian (Progress: 76%)
    • th-TH - Thai (Progress: 95%)
    • uk-UA - Ukranian (Progress: 84%)
    • zh-CN - Chinese Simplified (Progress: 100%)
    • zh-TW - Chinese Traditional (Progress: 61%)

PR Status :

  • Overall Status : Done
  • Commits : Done
  • Synced to base (Collapse:main) : Yes
  • Build status : OK
  • Crashing : No
  • Bug found caused by PR : -
  • Known Issues:
    • [Regression][High Priority] Game Config's API is not changed while changing the games (Assignee: @neon-nyan) Fixed as per 052cb94
    • [High Priority] Fix deleted assets still getting downloaded while updating Honkai: Star Rail and Zenless Zone Zero (Assignee: @neon-nyan) Fixed as per f87ef76
      • Backport the changes to Stable branch
    • [High Priority] Adjust Video Assets metadata parser for Honkai Impact 3rd v8.8 (Assignee: @neon-nyan) Fixed as per bd26158
      • Adjust struct field position for video availability flags
      • Fix LINQ selector on Collapse side to ignore unavailable flags
      • Reduce dependency on HTTP Status Code checks and use flags from video asset metadata instead.
      • Backport the changes to Stable branch
    • [Medium Priority] Fix gateway URL for Game Repair and Cache Update for Honkai: Star Rail (Assingee: @neon-nyan)
      • Backport the changes to Stable branch

Templates

Changelog Prefixes
  **[New]**
  **[Imp]**
  **[Fix]**
  **[Loc]**
  **[Doc]**

Cryotechnic and others added 26 commits March 18, 2026 06:05
Add full async preload download flow and harden progress/status callbacks.

- Implement StartPackageDownload as an async method (with NoOptimization/NoInlining) that initializes the plugin COM, queries total and already-downloaded sizes, ensures disk space, starts the preload task and awaits it. Handles cancellation, exceptions, and updates Status/IsRunning and logging.
- Implement IsPreloadCompleted to check preload completion by comparing downloaded vs total size via plugin calls (with error handling).
- Add defensive try/catch around UpdateProgressCallback and UpdateStatusCallback to prevent unhandled exceptions from crossing reverse P/Invoke boundaries (which would cause FailFast). Mirror aggregate progress into per-file fields, compute speeds/time left safely, and log swallowed exceptions.
- Update StartPackageVerification comment to note verification is included in preload, and relax an OperationCanceledException catch condition to always handle cancellations.
- Add additional debug/error logging throughout to aid troubleshooting.
Register a native per-file progress callback for plugins and use it to populate per-file progress fields.

- Introduces an unmanaged Cdecl delegate and GCHandle to hold a reverse P/Invoke callback (OnPerFileProgressCallback) and safe registration/unregistration helpers (TryRegisterPerFileProgressCallback, UnregisterPerFileProgressCallback).
- Calls registration before starting preload/download and ensures unregistration in finally blocks.
- OnPerFileProgressCallback updates per-file bytes/percentage inside a try/catch (must not throw when invoked from native AOT).
- Adjusts progress reporting: when the plugin provides per-file updates, use that data (and only mirror speed from aggregate); otherwise fall back to mirroring aggregate values into per-file fields.
- Adds PluginInfo.EnablePerFileProgressCallback and DisablePerFileProgressCallback which call the plugin export SetPerFileProgressCallback (Cdecl) and log failures.
100% reviewed source file: 'en_US.json'
on 'de_DE'.
Adds @perfectdelusions as a contributor for translation.

This was requested by bagusnl [in this
comment](#866 (comment))

[skip ci]
100% reviewed source file: 'en_US.json'
on 'ja_JP'.
100% reviewed source file: 'en_US.json'
on 'ja_JP'.
# Main Goal
Implement robust plugin-based preload, install, and update workflows
with per-file progress tracking, proper exception safety across P/Invoke
boundaries, and full `IGameInstallManager` compliance.

This pull request introduces significant improvements to the
plugin-based game installation system, with a focus on adding robust
per-file progress tracking and enhancing exception safety across reverse
P/Invoke boundaries.

## PR Status :
- Overall Status : Done
- Commits : Done
- Synced to base (Collapse:main) : **Yes**
- Build status : **OK**
- Crashing : **No**
- Bug found caused by PR : 0

### Templates

<details>
  <summary>Changelog Prefixes</summary>
  
  ```
    **[New]**
    **[Imp]**
    **[Fix]**
    **[Loc]**
    **[Doc]**
  ```

</details>



**Key changes include:**

### Per-file Progress Tracking and Plugin Integration

- **[New]** Added support for per-file progress callbacks in
`PluginGameInstallWrapper`, enabling more granular progress reporting
during game installation and download. This includes defining a new
delegate, registering/unregistering the callback with the plugin, and
updating progress fields accordingly.
[[1]](diffhunk://#diff-6d567c471f08bddcc31eeaa19f72ae7f3b5ac31e87b270a3f617163d4abd22e3R32-R34)],
[[2]](diffhunk://#diff-6d567c471f08bddcc31eeaa19f72ae7f3b5ac31e87b270a3f617163d4abd22e3R68-R71)],
[[3]](diffhunk://#diff-6d567c471f08bddcc31eeaa19f72ae7f3b5ac31e87b270a3f617163d4abd22e3R112-R165)],
[[4]](diffhunk://#diff-6d567c471f08bddcc31eeaa19f72ae7f3b5ac31e87b270a3f617163d4abd22e3L199-R326)],
[[5]](diffhunk://#diff-6d567c471f08bddcc31eeaa19f72ae7f3b5ac31e87b270a3f617163d4abd22e3R360-R361)])
- **[New]** Implemented new methods in `PluginInfo` to register and
unregister the per-file progress callback with the plugin via exported
functions, with error handling and logging.
([[CollapseLauncher/Classes/Plugins/PluginInfo.csR332-R368](diffhunk://#diff-214962c07ee46ad27a3948675104d996ad7484aefe8ceec5b816b7cf9e5e9920R332-R368)])
- **[Imp]** Added guard in `TryRegisterPerFileProgressCallback` to
prevent leaking a GCHandle if the method is called more than once
without a matching unregister.
- **[Imp]** `Status.IsIncludePerFileIndicator` is now set to
`_hasPerFileProgress` after callback registration, so the UI correctly
shows or hides the per-file progress indicator based on plugin
capability.

### Exception Handling and Stability

- **[Imp]** Wrapped all reverse P/Invoke callbacks
(`UpdateProgressCallback`, `UpdateStatusCallback`, and the new per-file
progress callback) in try/catch blocks to prevent unhandled exceptions
from causing FailFast crashes, and added logging for swallowed
exceptions.
[[1]](diffhunk://#diff-6d567c471f08bddcc31eeaa19f72ae7f3b5ac31e87b270a3f617163d4abd22e3L265-R405)],
[[2]](diffhunk://#diff-6d567c471f08bddcc31eeaa19f72ae7f3b5ac31e87b270a3f617163d4abd22e3L298-R452)],
[[3]](diffhunk://#diff-6d567c471f08bddcc31eeaa19f72ae7f3b5ac31e87b270a3f617163d4abd22e3R467-R476)],
[[4]](diffhunk://#diff-6d567c471f08bddcc31eeaa19f72ae7f3b5ac31e87b270a3f617163d4abd22e3R495-R499)])
- **[Fix]** `StartPackageDownload` now rethrows general exceptions after
logging and Sentry reporting, preventing silent failures that would
cause the verify→install pipeline to proceed with incomplete files.
- **[Fix]** Added general `catch (Exception)` block to
`StartPackageInstallation` with Sentry reporting and rethrow, matching
`StartPackageDownload`'s error-handling pattern.
- **[Fix]** `IsPreloadCompleted` now propagates
`OperationCanceledException` instead of swallowing it as `false`, making
cancellation distinguishable from "not completed".
- **[Fix]** `Status.IsCompleted` is now only set to `true` on successful
completion in both `StartPackageDownload` and
`StartPackageInstallation`, tracked via a `bool isSuccess` flag.
Previously it was set unconditionally in `finally`, making failures
appear as completions.

### Download and Installation Workflow Improvements

- **[Imp]** Refactored `StartPackageDownload` and
`StartPackageInstallation` to integrate per-file progress
registration/unregistration and to provide detailed logging and status
updates throughout the process.
[[1]](diffhunk://#diff-6d567c471f08bddcc31eeaa19f72ae7f3b5ac31e87b270a3f617163d4abd22e3L199-R326)],
[[2]](diffhunk://#diff-6d567c471f08bddcc31eeaa19f72ae7f3b5ac31e87b270a3f617163d4abd22e3R360-R361)])
- **[Imp]** Improved fallback logic for progress reporting when per-file
progress is not available, ensuring backward compatibility with older
plugins.
([[CollapseLauncher/Classes/Plugins/PluginGameInstallWrapper.csL298-R452](diffhunk://#diff-6d567c471f08bddcc31eeaa19f72ae7f3b5ac31e87b270a3f617163d4abd22e3L298-R452)])

### Functional Enhancements

- **[New]** Implemented the `IsPreloadCompleted` method to accurately
check if a preload download is complete by querying the plugin for total
and downloaded sizes, with error handling.
([[CollapseLauncher/Classes/Plugins/PluginGameInstallWrapper.csL415-R598](diffhunk://#diff-6d567c471f08bddcc31eeaa19f72ae7f3b5ac31e87b270a3f617163d4abd22e3L415-R598)])
- **[New]** Implemented `UpdateCompletenessStatus` to manage
`IsRunning`/`IsCompleted`/`IsCanceled` state, progress indeterminate
flags, and Discord presence updates, matching the `InstallManagerBase`
convention.
- **[New]** Implemented `CleanUpGameFiles` to scan and remove residual
temp/staging files under `{GameDirPath}\TempPath\`, with support for the
`FileCleanupPage` dialog UI or direct deletion.
- **[Fix]** Fixed `Locale.Lang` → `Locale.Current.Lang` for all
localization string accesses in `UpdateStatusCallback`, since `Lang` is
an instance property on the `Locale` singleton.

### Dependency Updates

- Updated the `Microsoft.NET.ILLink.Tasks` NuGet package from version
10.0.4 to 10.0.5 across multiple projects.
[[1]](diffhunk://#diff-5bf3fa83f98fe8daf7c49a3e3d3527606da7a229c6c426e3f1c4589f9d5201a2L144-R146)],
[[2]](diffhunk://#diff-d995168d6cf0ddb519c9cefd49fc4b2c2dcb883b1e1659b235b2b7588cd9e174L44-R46)],
[[3]](diffhunk://#diff-1d488b2cd859ba970f407cfbd0b9fa172f3af4b1a552cfb0d1513703ee5eca10L23-R25)],
[[4]](diffhunk://#diff-380527d5b33abffbfdc0f985d1a4cc21db5a3a02d491e3d6faeb1a8221f91e78L7-R9)],
[[5]](diffhunk://#diff-e1e16457c4744398ddc7e200170ca02f199d9a91cfca304605360451fb395d99L7-R9)])
- Added `Microsoft.NETFramework.ReferenceAssemblies` version 1.0.3 as a
new dependency in `Hi3Helper.TaskScheduler`.
([[Hi3Helper.TaskScheduler/packages.lock.jsonR20-R28](diffhunk://#diff-f2a0d3ab578dcfda2cf3cd16b2233a855fcee0a591090a27c0b0dec5a540cdb1R20-R28)])

### Miscellaneous

- **[Loc]** Minor language improvement in the FFmpeg installation lock
message in `en_US.json`.
([[Hi3Helper.Core/Lang/en_US.jsonL563-R563](diffhunk://#diff-a3d62fecc34be7c1b6da28f60fa8ff816b5b7644582602d1888a759485f5a4e8L563-R563)])
+ Fix HomePage navigated on cancelling background activity while the game isn't displayed
Comment on lines +331 to +338
int previousStackLimit = LauncherFrame.CacheSize;
LauncherFrame.Navigate(pageType, null, transitionInfo ?? new DrillInNavigationTransitionInfo());

if (isForceLoad)
{
LauncherFrame.BackStack.Clear();
LauncherFrame.CacheSize = 0;
}

This comment was marked as outdated.

};

NavigationViewControl.FooterMenuItems.Add(new NavigationViewItem { Icon = IconFilesCleanup, Tag = "filescleanup"}.BindNavigationViewItemText(Locale.Current, "Lang._FileCleanupPage.Title"));
NavigationViewControl.FooterMenuItems.Add<NavigationViewItem>("Lang._GameSettingsPage.PageTitle", "", gspPageType);

This comment was marked as outdated.

Just realized that the filtering of the asset is still being redirected to FilterSophonPatchAssetList, which is unused rather than to FilterAssetList. This causes the supposedly deleted assets to get included, causing files to be redownloaded if not exist
+ Reduce check time for CG files as it should parse the CG category correctly
neon-nyan and others added 5 commits April 5, 2026 23:51
This due to postproc being under GPL. We cannot use this part of the library.
+ Fix broken cutscene detection due to unmatching file size reported by metadata vs. the actual size reported by the URL (good job, HoYo. As always :])
+ Dynamically loads Cache Update's unused file ignore list from preset config.
100% reviewed source file: 'en_US.json'
on 'id_ID'.
100% reviewed source file: 'en_US.json'
on 'zh_CN'.
Comment on lines +509 to +517
InstallProgressState.Removing => string.Format("Deleting" + ": " + Locale.Current.Lang._Misc.PerFromTo, _updateProgressProperty.StateCount, _updateProgressProperty.StateCountTotal),
InstallProgressState.Idle => Locale.Current.Lang._Misc.Idle,
InstallProgressState.Install => string.Format(Locale.Current.Lang._Misc.Extracting + ": " + Locale.Current.Lang._Misc.PerFromTo, _updateProgressProperty.StateCount, _updateProgressProperty.StateCountTotal),
InstallProgressState.Verify or InstallProgressState.Preparing => string.Format(Locale.Current.Lang._Misc.Verifying + ": " + Locale.Current.Lang._Misc.PerFromTo, _updateProgressProperty.StateCount, _updateProgressProperty.StateCountTotal),
_ => string.Format((!_updateProgressProperty.IsUpdateMode ? Locale.Current.Lang._Misc.Downloading : Locale.Current.Lang._Misc.Updating) + ": " + Locale.Current.Lang._Misc.PerFromTo, _updateProgressProperty.StateCount, _updateProgressProperty.StateCountTotal)
};

Status.ActivityStatus = stateString;
Status.ActivityAll = string.Format(Locale.Current.Lang._Misc.PerFromTo, _updateProgressProperty.AssetCount, _updateProgressProperty.AssetCountTotal);
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bug: The UpdateStatusCallback method no longer uses null-conditional operators when accessing locale strings. This can cause a NullReferenceException that is silently caught, freezing the installation progress UI.
Severity: MEDIUM

Suggested Fix

Restore the null-conditional operators (?.) when accessing properties of Locale.Current.Lang._Misc within the UpdateStatusCallback method. This ensures that if locale data is null, the status string becomes null without throwing an exception, preventing the UI from freezing.

Prompt for AI Agent
Review the code at the location below. A potential bug has been identified by an AI
agent.
Verify if this is a real issue. If it is, propose a fix; if not, explain why it's not
valid.

Location: CollapseLauncher/Classes/Plugins/PluginGameInstallWrapper.cs#L509-L517

Potential issue: In the `UpdateStatusCallback` method, accesses to
`Locale.Current.Lang._Misc` properties were changed to remove the null-conditional
operator (`?.`). If `Locale.Current.Lang` or `Locale.Current.Lang._Misc` is null, for
instance due to a locale loading failure, a `NullReferenceException` will be thrown.
While a `try/catch` block prevents a crash, it silently swallows the exception, which
stops `Status.ActivityStatus` from being updated. This results in the installation
progress UI freezing with stale status information instead of gracefully handling the
missing locale strings.

Comment on lines +71 to +76
if (asset.FT != FileType.Video ||
string.IsNullOrEmpty(asset.RN) ||
useFastCheck)
{
return true;
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bug: The method TryIsAssetRemoteSizeEquals incorrectly returns true for non-video files with a size mismatch, causing the repair process to skip hash verification for corrupted assets.
Severity: HIGH

Suggested Fix

Modify the logic so that TryIsAssetRemoteSizeEquals is only called for video files. Alternatively, change TryIsAssetRemoteSizeEquals to return false for non-video files. This will ensure that files with a size mismatch proceed to the standard hash verification and repair flow.

Prompt for AI Agent
Review the code at the location below. A potential bug has been identified by an AI
agent.
Verify if this is a real issue. If it is, propose a fix; if not, explain why it's not
valid.

Location:
CollapseLauncher/Classes/RepairManagement/HonkaiV2/HonkaiRepairV2.Check.Generic.cs#L71-L76

Potential issue: When a game asset has a size mismatch, the repair logic calls
`TryIsAssetRemoteSizeEquals`. For any non-video file, this method immediately returns
`true`. This causes the calling function, `IsHashMatchedAuto`, to incorrectly treat the
asset as valid and skip the required hash verification step. As a result, corrupted or
incomplete non-video game files that have a size mismatch will not be detected or
repaired by the system.

Comment on lines +119 to +121
string assetName = (gameLanguageType == AudioLanguageType.Japanese
? entry.Value.PathJp
: entry.Value.PathCn) ?? throw new NullReferenceException();
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bug: A NullReferenceException is thrown if a video asset path is null, which aborts the entire parallel asset retrieval process and returns an empty list.
Severity: MEDIUM

Suggested Fix

Instead of throwing an exception, gracefully handle null path entries. For example, use a continue statement or a null-conditional check to skip the problematic entry and log a warning, allowing the Parallel.ForEachAsync loop to process the remaining valid assets.

Prompt for AI Agent
Review the code at the location below. A potential bug has been identified by an AI
agent.
Verify if this is a real issue. If it is, propose a fix; if not, explain why it's not
valid.

Location:
CollapseLauncher/Classes/RepairManagement/HonkaiV2/HonkaiRepairV2.AsbExt.Video.cs#L119-L121

Potential issue: In the `ImplCheckAndAdd` method, a null-coalescing operator is used to
throw a `NullReferenceException` if `entry.Value.PathJp` or `entry.Value.PathCn` is
null. This code runs inside a `Parallel.ForEachAsync` loop without a `try/catch` block.
If a null path is encountered, the exception will propagate and abort the entire video
asset retrieval process, causing the method to return an empty list. This prevents any
video assets from being processed if even one entry has a missing path.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants